package com.tbit.uqbike.service.business.impl;

import com.github.pagehelper.PageInfo;
import com.github.pagehelper.page.PageMethod;
import com.tbit.uqbike.constant.MapConstant;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.business.Point;
import com.tbit.uqbike.object.pojo.dto.AccountSpikeDTO;
import com.tbit.uqbike.object.pojo.dto.AccountSpikeGetDTO;
import com.tbit.uqbike.object.pojo.vo.AccountSpikeVo;
import com.tbit.uqbike.object.pojo.vo.BatchOperationMsgVO;
import com.tbit.uqbike.object.value.LoginInfo;
import com.tbit.uqbike.object.view.JsonResult;
import com.tbit.common.entity.view.PageResult;
import com.tbit.common.entity.view.Result;
import com.tbit.uqbike.service.business.AccountSpikeService;
import com.tbit.uqbike.webmanager.dao.core.AccountSpikeDao;
import com.tbit.uqbike.webmanager.util.adaPay.AdaPayUtil;
import com.tbit.uqbike.webmanager.util.calibreate.GpsCorrect;
import com.tbit.uqbike.webmanager.util.excel.ExcelUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;

/**
 * 道钉管理
 *
 * @Author LHX
 * @ClassName AccountSpikeServiceImpl
 * @Description
 * @date 2023/5/12 11:04
 * @Version 1.0
 */
@Slf4j
@Service
public class AccountSpikeServiceImpl implements AccountSpikeService {

    @Autowired
    private AccountSpikeDao accountSpikeDao;

    @Override
    public PageResult<AccountSpikeVo> queryPage(AccountSpikeGetDTO dto) {
        PageInfo<AccountSpikeVo> pageInfo = PageMethod.startPage(dto.getPage(), dto.getSize()).doSelectPageInfo(() -> accountSpikeDao.querySpike(dto));
        return new PageResult<>(dto.getPage(), dto.getSize(), pageInfo.getTotal(), pageInfo.getPages(), pageInfo.getList());
    }

    @Override
    public Result<String> updateAccountSpike(AccountSpikeDTO dto, LoginInfo loginInfo) {
        // 道钉编号和mac地址唯一 校验
        if (accountSpikeDao.selectUnique(dto) < 0) {
            return Result.error("该设备不存在");
        }
        dto.setOperateId(loginInfo.getId());
        dto.setUpdateTime(new Date());
        Point point = calibrateOffSet(dto.getLonC(), dto.getLatC(), dto.getMapType());
        dto.setLon(point.getX()).setLat(point.getY());
        accountSpikeDao.updateAccountSpike(dto);
        return Result.success();
    }

    @Override
    public Result<String> addAccountSpike(AccountSpikeDTO dto, LoginInfo login) {
        // 道钉编号和mac地址唯一 校验
        if (accountSpikeDao.selectUnique(dto) > 0) {
            return Result.error("该设备已存在");
        }
        dto.setAddTime(new Date());
        dto.setOperateId(login.getId());
        //获取原始经纬度
        Point point = calibrateOffSet(dto.getLonC(), dto.getLatC(), dto.getMapType());
        dto.setLon(point.getX()).setLat(point.getY());
        accountSpikeDao.addAccountSpike(dto);
        return Result.success();
    }

    @Override
    public Result exportAccountSpike(AccountSpikeGetDTO dto) {
        dto.setPage(1);
        dto.setSize(65535);
        PageResult<AccountSpikeVo> accountSpikeVoPageResult = queryPage(dto);
        List<AccountSpikeVo> list = accountSpikeVoPageResult.getList();
        ExcelUtil<AccountSpikeVo> excelUtil = new ExcelUtil<>(AccountSpikeVo.class);
        JsonResult jsonResult = excelUtil.exportExcel(list, "道钉信息导出记录");
        return Result.success(jsonResult.getData());
    }

    @Override
    public Result batchAddOrUpdate(MultipartFile file, Integer batchType, Integer accountId, LoginInfo login) {
        //解析excel
        List<AccountSpikeDTO> accountSpikeDTOS = analysisExcel(file);
        if (accountSpikeDTOS.isEmpty()) {
            return Result.error("请正确填写数据");
        }
        //List转化Map key：道钉编号 value：道钉信息
        Map<String, AccountSpikeDTO> spikedMap = new HashMap<>();
        //新增或修改道钉编号集合
        List<String> spikeNoList = new ArrayList<>();
        List<String> successList = new ArrayList<>();
        List<String> fileList = new ArrayList<>();
        for (AccountSpikeDTO accountSpikeDTO : accountSpikeDTOS) {
            accountSpikeDTO.setAccountId(accountId);
            spikedMap.put(accountSpikeDTO.getSpikeNo(), accountSpikeDTO);
            //必填数据为空直接放进失败集合
            if (accountSpikeDTO.getSuccessOrFileType() == 1) {
                fileList.add(accountSpikeDTO.getSpikeNo());
                continue;
            }
            spikeNoList.add(accountSpikeDTO.getSpikeNo());
        }
        //根据道钉编号查询 系统中的道钉编号
        List<String> indbspikes = accountSpikeDao.selectBySpike(spikeNoList, accountId);
        //构建返回对象
        BatchOperationMsgVO batchOperationMsgVO = new BatchOperationMsgVO();
        //根据batchType判断新增或者修改
        if (batchType == 0) {
            //新增道钉编号已存在，默认失败,同时剔除掉新增列表
            fileList.addAll(indbspikes);
            spikeNoList.removeAll(indbspikes);

            for (int i = 0; i < spikeNoList.size(); i++) {
                //默认使用高德地图
                AccountSpikeDTO accountSpikeDTO = spikedMap.get(spikeNoList.get(i)).setMapType(2);
                addAccountSpike(accountSpikeDTO, login);
            }

            successList.addAll(spikeNoList);
            batchOperationMsgVO.setSuccessList(successList).setFailList(fileList);
            return Result.success("部分数据新增成功", batchOperationMsgVO);
        } else if (batchType == 1) {
            //修改道钉编号不存在，默认失败，并同时提出掉修改列表
            spikeNoList.removeAll(indbspikes);
            fileList.addAll(spikeNoList);

            for (int i = 0; i < indbspikes.size(); i++) {
                AccountSpikeDTO accountSpikeDTO = spikedMap.get(indbspikes.get(i)).setMapType(2);
                accountSpikeDTO.setSqlType(1);
                updateAccountSpike(spikedMap.get(indbspikes.get(i)), login);
            }

            successList.addAll(indbspikes);
            batchOperationMsgVO.setSuccessList(successList).setFailList(fileList);
            return Result.success("部分数据修改成功", batchOperationMsgVO);
        }
        return Result.error("参数错误");
    }

    @Override
    public Result<String> deleteAccountSpike(AccountSpikeDTO dto) {
        dto.setDelFlag(1);
        dto.setState(0);
        accountSpikeDao.updateAccountSpike(dto);
        return Result.success();
    }


    /**
     * 校准坐标点
     */
    public Point calibrateOffSet(double lo, double la, int mapType) {
        Point point = new Point(lo, la);
        if (MapConstant.MAP_BAIDU == mapType) {
            double[] latlng = GpsCorrect.oriToBaidu(la, lo);
            point.setX(latlng[1]);
            point.setY(latlng[0]);
        } else if (MapConstant.MAP_GOOGLE == mapType) {
            double[] latlng = GpsCorrect.oriToGoogle(la, lo);
            point.setX(latlng[1]);
            point.setY(latlng[0]);
        }

        return point;
    }

    /**
     * 解析excel 工具类无法处理纯数字带小数点的问题
     *
     * @param file
     * @return
     */
    public List<AccountSpikeDTO> analysisExcel(MultipartFile file) {
        List<AccountSpikeDTO> list = new ArrayList<>();
        try (Workbook wb = WorkbookFactory.create(Objects.requireNonNull(AdaPayUtil.MultipartFileToFile(file)))) {
            //道钉编号index
            Integer spikeNoIndex = null;
            //道钉类型index
            Integer typeIndex = null;
            //mac地址index
            Integer macIndex = null;
            //地址index
            Integer addressIndex = null;
            //状态index
            Integer stateIndex = null;
            //经度index
            Integer lonCIndex = null;
            //纬度index
            Integer latCIndex = null;
            Sheet sheet = wb.getSheetAt(0);
            boolean flag = true;
            for (Row row : sheet) {
                if (flag) {
                    //第一行为标题
                    Iterator<Cell> cellIterator = row.cellIterator();
                    while (cellIterator.hasNext()) {
                        Cell cell = cellIterator.next();
                        if ("道钉编号".equals(cell.getStringCellValue())) {
                            spikeNoIndex = cell.getColumnIndex();
                        }
                        if ("道钉类型".equals(cell.getStringCellValue())) {
                            typeIndex = cell.getColumnIndex();
                        }
                        if ("MAC地址".equals(cell.getStringCellValue())) {
                            macIndex = cell.getColumnIndex();
                        }
                        if ("地址".equals(cell.getStringCellValue())) {
                            addressIndex = cell.getColumnIndex();
                        }
                        if ("状态".equals(cell.getStringCellValue())) {
                            stateIndex = cell.getColumnIndex();
                        }
                        if ("经度".equals(cell.getStringCellValue())) {
                            lonCIndex = cell.getColumnIndex();
                        }
                        if ("纬度".equals(cell.getStringCellValue())) {
                            latCIndex = cell.getColumnIndex();
                        }
                    }
                    if (spikeNoIndex == null || typeIndex == null || macIndex == null || addressIndex == null || stateIndex == null || latCIndex == null) {
                        throw new BaseException("excel数据有误");
                    }
                    flag = false;
                    continue;
                }
                //后面的为数据
                String spikeNo = null;
                Integer type = null;
                String mac = null;
                String address = "";
                Integer state = null;
                Double lonC = null;
                Double latC = null;
                if (row.getCell(spikeNoIndex) != null) {
                    spikeNo = row.getCell(spikeNoIndex).toString();
                }
                if (row.getCell(typeIndex) != null) {
                    type = Double.valueOf(row.getCell(typeIndex).toString()).intValue();
                }
                if (row.getCell(macIndex) != null) {
                    mac = row.getCell(macIndex).toString();
                }
                if (row.getCell(addressIndex) != null) {
                    address = row.getCell(addressIndex).toString();
                }
                if (row.getCell(stateIndex) != null) {
                    state = Double.valueOf(row.getCell(stateIndex).toString()).intValue();
                }
                if (lonCIndex != null && row.getCell(lonCIndex) != null) {
                    lonC = Double.valueOf(row.getCell(lonCIndex).toString());
                }
                if (row.getCell(latCIndex) != null) {
                    latC = Double.valueOf(row.getCell(latCIndex).toString());
                }

                AccountSpikeDTO accountSpikeDTO = new AccountSpikeDTO();
                accountSpikeDTO.setSpikeNo(spikeNo);
                accountSpikeDTO.setType(type);
                accountSpikeDTO.setMac(mac);
                accountSpikeDTO.setAddress(address);
                accountSpikeDTO.setState(state);
                accountSpikeDTO.setLonC(lonC);
                accountSpikeDTO.setLatC(latC);
                if (accountSpikeDTO.getSpikeNo() == null || accountSpikeDTO.getType() == null || accountSpikeDTO.getMac() == null || accountSpikeDTO.getState() == null || accountSpikeDTO.getLonC() == null || accountSpikeDTO.getLatC() == null) {
                    accountSpikeDTO.setSuccessOrFileType(1);
                } else {
                    accountSpikeDTO.setSuccessOrFileType(0);
                }
                list.add(accountSpikeDTO);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return list;
    }

}
